// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using System.Linq;
using NUnit.Framework;
using ValidationAspects;
using ValidationAspects.Sdk;

namespace TestValidationAspects.Sdk
{
	[TestFixture]
	public class TestInlineValidatorFactory
	{
		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_constructor_throws_for_null_param()
		{
			new InlineValidatorFactory<object>(null);
		}

		[Test]
		public void Test_Create()
		{
			object valueFromValidator = null;
			IValidationContext contextFromValidator = null;
			var factory = new InlineValidatorFactory<object>((v, c) =>
			                                                 {
			                                                 	valueFromValidator = v;
			                                                 	contextFromValidator = c;
			                                                 });

			object value = new object();
			IValidationContext context = new MockValidationContext();
			factory.Create<object>().Invoke(value, context);

			Assert.AreSame(value, valueFromValidator);
			Assert.AreSame(context, contextFromValidator);
		}

		[Test]
		public void Test_Create_when_adaptation_is_required()
		{
			Base valueFromValidator = null;
			IValidationContext contextFromValidator = null;
			var factory = new InlineValidatorFactory<Base>((v, c) =>
			                                               {
			                                               	valueFromValidator = v;
			                                               	contextFromValidator = c;
			                                               });

			Derived value = new Derived();
			IValidationContext context = new MockValidationContext();
			factory.Create<Derived>().Invoke(value, context);

			Assert.AreSame(value, valueFromValidator);
			Assert.AreSame(context, contextFromValidator);
		}

		[Test]
		public void Test_usage_from_a_custom_attribute()
		{
			Dummy dummy = new Dummy {Username = "Mike"};

			ValidationResult result = dummy.Validate();
			Assert.IsTrue(result.IsValid);

			dummy.Username = "Mr Mike";
			result = dummy.Validate();
			Assert.IsFalse(result.IsValid);
			Assert.AreEqual("value contains spaces", result.Messages.First());
		}

		#region Mocks
		public class Base {}

		public class Derived : Base {}

		[AttributeUsage(AttributeTargets.Property)]
		public class NoSpacesAttribute : ValidatorAttribute
		{
			#region Overrides of ValidatorAttribute
			public override IValidatorFactory Factory
			{
				get { return new InlineValidatorFactory<string>((v, c) => { if (v != null && v.Contains(" ")) throw new ValidationException("value contains spaces"); }); }
			}
			#endregion
		}

		public class Dummy
		{
			[NoSpaces]
			public string Username { get; set; }
		}
		#endregion
	}
}